/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package poproject.CombinatorialTask;

import java.util.*;

/** @class Word
 * 
 * Klasa reprezentująca słowa wprowadzone przez użytkowanika
 * na podstawie, których będzie rozwiązywany problem kombinatoryczny
 * oparty na zasadach wynikających z programy SendMoreMoney.java.
 * Dążymy więc do znalezienia wartości unikalnych liter w kombinacji słów
 * i sprawdzeniania czy isteniej rozwiązanie postawionego problemu.
 * 
 * @author Jan Karaś
 */
public class Word {

    // ********************** POLA PRYWATNE ********************** //
    
    private String mWordStr;                //< Pole przechowujące słowo 
    private int mMaxWordValue;              //< Pole przechowujące maksymalną wartość jaką może przyjąć słowo 
    private Integer mWordValue;                 //< Pole reprezentuje wartość liczbową słowa
    private ArrayList<Integer> mWordWeights;//< Lista wag zależnych od długości słowa
    private Sign mWordSign;                 //< Działania jakiemu będzie poddawane słowo
    
    // ********************** POLA PUBLICZNE ********************** //
    
    public enum Sign{Plus, Minus, Equal, Unknown};  /// Typ wyliczeniowy określający znak stojący przy słowie
    

    /**
     * Konstruktor domyślny ustawiający domyślne wartości słowa.
     */
    public Word()
    {
        mWordStr = "";
        mWordValue = null;
        mWordSign = Sign.Unknown;
        mMaxWordValue = 0;
        mWordWeights = new ArrayList<>();          
    }
    
    public Word(String nWord)
    {
        mWordWeights = new ArrayList<>();
        mWordStr = nWord;   
        mWordValue = null;
        determineWordSign();
        generateWordValues();
    }
       
    // ********************** METODY PUBLICZNE ********************** //
    
    /**
     * Metoda pozwalająca na ustawienie dowolnego słowa.
     * @param nWord Przechowywane słowo
     */
    public void setWord(String nWord)
    {
        mWordStr = nWord;        
        determineWordSign();
        generateWordValues();
    }
    
    /**
     * Metoda pozwalająca na dostęp do przechowywanego słowa.
     * @return Przechowywane słowo.
     */
    public String getWord()
    {
        return mWordStr;
    }
    
    /**
     * Metoda pozwalająca na pobranie listy wag słowa. Każda litera w słowie
     * ma ściśle określoną wagę np:
     * SEND = 1000*S + 100*E + 10*N + 1*D
     * 
     * @return Lista wag danego słowa
     */
    public ArrayList<Integer> getWeights()
    {              
        return mWordWeights;
    }
    
    /**
     * Metoda pozwalająca na pobranie maksymalnej wartości jaką może przyjąć
     * słowo.
     * 
     * @return Maksymalna wartość jaką może przyjąć słowo
     */
    public int getMaxWordValue()
    {
        return mMaxWordValue;
    }
    
    /**
     * Metoda pozwalająca na zwrócenie znaku jaki stał przy słowie
     * @return 
     */
    public Sign getWordSign()
    {
        return mWordSign;
    }
    
    /**
     * Ustawienie wartości słowa.
     * Metoda umożliwia ustawienie wartości słowa znalezione podczas poszukiwań
     * z wykorzystaniem odpowiednie metody.
     * @param value Wartość liczbowa słowa
     */
    public void setWordValue(Integer value)
    {
        mWordValue = value;
    }
    
    /**
     * Pobranie wartości słowa.
     * Metoda umożliwia wyznaczenie pobranie wartości słowa. Wartość jest 
     * wyznaczana na podstawie rozwiązania problemu kombinatorycznego.
     * @return Wartość liczbowa słowa
     */
    public Integer getWordValue()
    {
        return mWordValue;
    }
    
    // ********************** METODY PRYWATNE ********************** //
    
    /**
     * Metoda prywatna wykorzystywana do generowania wag słowa.
     */
    private void generateWordValues()
    {
        switch(mWordSign)
        {
            case Plus:
            case Equal:
            case Unknown:
                for(int i=(mWordStr.length()-1); i>=0; i--)
                    mWordWeights.add((int)Math.pow(10, i)); 
                break;
            case Minus:
                for(int i=(mWordStr.length()-1); i>=0; i--)
                    mWordWeights.add(-(int)Math.pow(10, i)); 
                break;
        }            
        
        mMaxWordValue = (int)Math.pow(10, mWordStr.length()) - 1;
    }
    
    
    /**
     * Metoda pozwalająca na określenie znaku jaki jest związany
     * z przechowywanym słowem.
     */
    private void determineWordSign()
    {
        String sign = Character.toString(mWordStr.charAt(0));
        switch (sign) {
            case "+":
                mWordSign = Sign.Plus;
                mWordStr = mWordStr.substring(1);
                break;
            case "-":
                mWordSign = Sign.Minus;
                mWordStr = mWordStr.substring(1);
                break;
            case "=":
                mWordSign = Sign.Equal;
                mWordStr = mWordStr.substring(1);
                break;                
            default:
                mWordSign = Sign.Unknown;
                break;
        }           
    }  
}
